home *** CD-ROM | disk | FTP | other *** search
- {
- GPC demo program for the Pipe unit.
- Inter-process communication using pipes on multi-tasking systems,
- emulated on single-tasking systems.
-
- Copyright (C) 1999-2001 Free Software Foundation, Inc.
-
- Author: Frank Heckenbach <frank@pascal.gnu.de>
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation, version 2.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
- As a special exception, if you incorporate even large parts of the
- code of this demo program into another program with substantially
- different functionality, this does not cause the other program to
- be covered by the GNU General Public License. This exception does
- not however invalidate any other reasons why it might be covered
- by the GNU General Public License.
- }
-
- program PipeDemo;
-
- uses GPC, Pipe;
-
- const
- ResultMessage : array [TWaitPIDResult] of TString =
- ('did not terminate with status ',
- 'terminated with status ',
- 'was teminated by signal ',
- 'was stopped by signal ',
- 'did something unexpected with status ');
-
- var
- ToInput : Text;
- FromOutput, FromStdErr : File;
- Process : PPipeProcess;
- WaitPIDResult : TWaitPIDResult;
- Status : Integer;
- Files : array [1 .. 2] of PAnyFile;
-
- { Check for output while reading input. }
- procedure CheckProcessOutput (TimeOut : LongInt);
- const Names : array [1 .. 2] of String [6] = ('Output', 'StdErr');
- var
- Nr, BytesRead : Integer;
- LastNr : static Integer = 0;
- Buffer : array [1 .. 256] of Char;
- begin
- Nr := - 1;
- while (Nr <> 0) and ((Files [1] <> nil) or (Files [2] <> nil)) do
- begin
- Nr := IOSelectRead (Files, TimeOut);
- if Nr < 0 then
- begin
- Writeln (StdErr, 'Error in `IOSelect''');
- Halt (1)
- end;
- if Nr > 0 then
- begin
- BlockRead (File (Files [Nr]^), Buffer, SizeOf (Buffer), BytesRead);
- if BytesRead = 0 then
- Files [Nr] := nil
- else
- begin
- if LastNr <> Nr then
- begin
- LastNr := Nr;
- Write ('[', Names [Nr], ']')
- end;
- Write (Buffer [1 .. BytesRead])
- end
- end
- end
- end;
-
- procedure DemoProcedure;
- var s : TString;
- begin
- Writeln (StdErr, 'Forking, but not executing another process...');
- while not EOF do
- begin
- Readln (s);
- Writeln ('Writing `', s, ''' to Output.');
- Writeln (StdErr, 'Writing `', s, ''' to Error.')
- end
- end;
-
- begin
- Writeln ('Demo for using pipes and forking. By default, the program will fork');
- Writeln ('and execute DemoProc as a separate executable, and emulate this on');
- Writeln ('limited operating systems (e.g., Dos). If you give the command line');
- Writeln ('parameter `-f'', the program will only fork, but not execute');
- Writeln ('another process, but rather an internal procedure.');
- Writeln;
- if PipeForking
- then Writeln ('Using fork on this system.')
- else Writeln ('Emulating fork on this system.');
- Writeln;
- { Also search for demoproc in the directory of this executable, if available }
- SetEnv (PathEnvVar, DirFromPath (ExecutablePath) + PathSeparator + GetEnv (PathEnvVar));
- { Start a process with pipes }
- {$I-}
- if ParamStr (1) = '-f'
- then Pipe (ToInput, (*@@anyfile*)AnyFile( FromOutput), (*@@anyfile*)AnyFile( FromStdErr), '', null, GetCEnvironment, Process, DemoProcedure)
- else Pipe (ToInput, (*@@anyfile*)AnyFile( FromOutput), (*@@anyfile*)AnyFile( FromStdErr), 'demoproc', null, GetCEnvironment, Process, nil);
- {$I+}
- if IOResult <> 0 then
- begin
- Writeln (StdErr, 'Could not create pipe to `demoproc''. Please compile `demoproc.pas'' first,');
- Writeln (StdErr, 'and make sure the resulting executable can be found in your PATH.');
- Halt (1)
- end;
-
- { Set the variables where the process' status will be stored. }
- Process^.Result := @WaitPIDResult;
- Process^.Status := @Status;
-
- Files [1] := (*@@anyfile*)PAnyFile( @FromOutput);
- Files [2] := (*@@anyfile*)PAnyFile( @FromStdErr);
-
- { Pipe some input to the process }
- CheckProcessOutput (0);
- Writeln (ToInput, 'foo');
- CheckProcessOutput (0);
- Sleep (1);
- Writeln (ToInput, 'bar');
- CheckProcessOutput (0);
-
- Close (ToInput); { It's important to close ToInput here, so the process
- will terminate. However, the effects of not closing ToInput are quite
- different under Unix (waiting for more input from FromOutput or
- FromStdErr) and Dos (never starting the process in the first place
- and therefore not getting any data from FromOutput and FromStdErr!). }
-
- { Read all the remaining output }
- CheckProcessOutput (- 1);
-
- Close (FromOutput);
- Close (FromStdErr);
- Writeln ('The process ', ResultMessage [WaitPIDResult], Status, '.');
- if (WaitPIDResult = PIDExited) and (Status = 0) then Writeln ('This means success.')
- end.
-